package com.cdxy;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author: tangy
 * @Date: 2021/12/26 14:22
 */
public class SqlGen {

    private final static Pattern tableNamePattern = Pattern.compile("@TableName\\(\"(.*?)\"\\)");
    private final static Pattern tableCommentPattern = Pattern.compile("@ApiModel\\(value=\".*?\", description=\"(.*?)\"\\)");
    private final static Pattern fieldCommentPattern = Pattern.compile("@ApiModelProperty\\(value=\"(.*?)\"\\)");
    private final static Pattern autoIdPattern = Pattern.compile("@TableId\\(value = \"(.*?)\",.*?\\)");
    private final static Pattern fieldNamePattern = Pattern.compile("private (.*?) (.*?);");

    public static void main(String[] args) {
        SqlGen wSqlGen = new SqlGen();

        List<String> wPatchList = wSqlGen.getFilePatch("D:\\project\\javaEE_project\\gra\\src\\main\\java\\com\\cdxy\\dmr\\dataObject\\AreaDO.java");


        for (String wPath : wPatchList) {

            String wSql = wSqlGen.getSql(wPath);
            System.err.println(wSql);
        }

    }

    // 获取入口文件夹下的文件
    private List<String> getFilePatch(String pRootPath) {

        File wFile = new File(pRootPath);

        // 如果是文件目录
        if (wFile.isDirectory()) {

            String[] a = wFile.list();

            List<String> wAbsolutePath = new ArrayList<>(a.length);

            for (String wPatch : a) {

                wAbsolutePath.add(wFile + File.separator + wPatch);
            }

            return wAbsolutePath;
        }
        else {
           String wDirectory =  wFile.getParent();

           wFile = new File(wDirectory);

           String[] a = wFile.list();

            List<String> wAbsolutePath = new ArrayList<>(a.length);

            for (String wPatch : a) {

                wAbsolutePath.add(wFile + File.separator + wPatch);
            }

            return wAbsolutePath;
        }

    }



    // 获取文件内容
    private String getSql(String pPatch) {
        String wTableComment = "";
        String wAutoId = "id";

        File file = new File(pPatch);
        StringBuilder result = new StringBuilder("CREATE TABLE `");
        try{
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));//构造一个BufferedReader类来读取文件

            String s = null;
            while((s = br.readLine()) !=null){//使用readLine方法，一次读一行

                if ("".equals(s)) {
                    continue;
                }

                // 去掉空格
                s = trime(s);

                // 注解
                if (s.charAt(0) == '@') {
                    Matcher wTableNameMatcher = tableNamePattern.matcher(s);
                    Matcher wTableCommentMatcher = tableCommentPattern.matcher(s);
                    Matcher wFieldCommentMatcher = fieldCommentPattern.matcher(s);
                    Matcher wAutoIdMatcher = autoIdPattern.matcher(s);


                    // 获取表名
                    if (wTableNameMatcher.find()){
                       String wTableName = wTableNameMatcher.group(1);

                       result.append(upLower(wTableName) + "` ( ");

                    }
                    // 获取表注释
                    else if (wTableCommentMatcher.find()) {
                        wTableComment = wTableCommentMatcher.group(1);

                        if (!"".equals(wTableComment)) {

                            wTableComment = " COMMENT='" + upLower(wTableComment) + "'";
                        }
                    }
                    // 获取字段注释
                    else if (wFieldCommentMatcher.find()) {
                        String wFieldComment = wFieldCommentMatcher.group(1);

                        // 在读一行获取字段
                        s = br.readLine();

                        // 获取字段名
                        Matcher wFieldNameMatcher = fieldNamePattern.matcher(s);
                        if (wFieldNameMatcher.find()) {

                            String wFieldType = wFieldNameMatcher.group(1);
                            String wFieldName = wFieldNameMatcher.group(2);

                            // 转换类型
                            wFieldType = convertType(wFieldType);

                            // 改为驼峰
                            wFieldName = upLower(wFieldName);

                            result.append("`")
                                    .append(wFieldName)
                                    .append("` ")
                                    .append(wFieldType)
                                    .append(" COMMENT '")
                                    .append(wFieldComment)
                                    .append("',");

                        }

                    }
                    // 自增长ID
                    else if (wAutoIdMatcher.find()) {
                        wAutoId = wAutoIdMatcher.group(1);

                        result.append("`")
                                .append(wAutoId)
                                .append("` int(11) unsigned NOT NULL AUTO_INCREMENT,");

                        // 跳过下一行字段
                        s = br.readLine();
                    }
                }
                // 其他
                else {

                    // 跳过序列化字段
                    if ("private static final long serialVersionUID = 1L;".equals(s)) {
                        continue;
                    }

                    // 获取字段名
                    Matcher wFieldNameMatcher = fieldNamePattern.matcher(s);
                    if (wFieldNameMatcher.find()) {

                        String wFieldType = wFieldNameMatcher.group(1);
                        String wFieldName = wFieldNameMatcher.group(2);

                        // 转换类型
                        wFieldType = convertType(wFieldType);

                        // 改为驼峰
                        wFieldName = upLower(wFieldName);

                        result.append("`")
                                .append(wFieldName)
                                .append("` ")
                                .append(wFieldType)
                                .append(",");

                    }

                }
            }
            br.close();
        }catch(Exception e){
            e.printStackTrace();
        }

        result.append("PRIMARY KEY (`" + wAutoId + "`) USING BTREE");
        result.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC");
        result.append(wTableComment);
        result.append(";");
        return result.toString();
    }

    // 将驼峰转换成_
    private String upLower(String pUp) {

        if ("".equals(pUp)) {
            return "";
        }

        StringBuilder sb = new StringBuilder();

        String wFirst = String.valueOf(pUp.charAt(0)).toLowerCase();

        sb.append(wFirst);



        for (int i = 1; i < pUp.length(); i++) {
            char wChar = pUp.charAt(i);

            // 将其他大写转换
            if ('A' < wChar && 'Z' > wChar) {
                String wOther = String.valueOf(wChar).toLowerCase();

                sb.append("_")
                        .append(wOther);
            }
            else {
                sb.append(wChar);
            }

        }

        return sb.toString();

    }

    // 去掉空格
    private String trime(String pString) {

        int i = 0;
        while (pString.charAt(i) == ' ') {
            i++;
        }
       return pString.substring(i);

    }

    // 将对象的类型转换成 SQL 类型
    private String convertType(String pType) {
        // Boolean -> "tinyint(1)"
        if ("Boolean".equals(pType)) {
            return "tinyint(1)";
        }
        // Integer -> "int(25)"
        else if ("Integer".equals(pType)) {
            return "int(25)";
        }

        // String -> "varchar(23)"
        else if ("String".equals(pType)) {
            return "varchar(23)";
        }

        // LocalDateTime -> "datetime DEFAULT CURRENT_TIMESTAMP"
        else if ("LocalDateTime".equals(pType)) {
            return "datetime DEFAULT CURRENT_TIMESTAMP";
        }

        // LocalDate -> "date"
        else if ("LocalDate".equals(pType)) {
            return "date";
        }

        throw new IllegalArgumentException(pType + "参数类型错误");
    }

}
